﻿using System;
using System.IO;
using System.Windows.Forms;
using ImageResizer.FileExplorer.Interface;
using ImageResizer.Properties;
using ImageResizer.Tools;

namespace ImageResizer
{
    public partial class FTPBrowser : Form
    {
        #region Private const
        /// <summary>
        /// Clé utilisée pour l'image des répertoires
        /// </summary>
        private const string FolderKey = "folder";

        /// <summary>
        /// Chaine indiquant qu'un noeud n'a pas encore été déployé
        /// </summary>
        private const string NotYetExpandedFolder = "*"; 
        #endregion

        #region Private vars
        /// <summary>
        /// Objet permettant de naviguer
        /// </summary>
        private static FileExplorer.Interface.IFileExplorer _fileExplorer;

        /// <summary>
        /// Le noeud sélectionné
        /// </summary>
        private TreeNode _currentNode;

        /// <summary>
        /// Mode d'affichage de la boite de dialogue
        /// </summary>
        private ModeEnum _mode;

        #region Gestion des icones pour les fichiers

        private ImageList _smallImageList = new ImageList();
        private ImageList _largeImageList = new ImageList();
        private IconListManager _iconListManager;

        #endregion

        #endregion

        #region CTOR
        /// <summary>
        /// CTOR
        /// </summary>
        public FTPBrowser(ModeEnum mode)
        {
            InitializeComponent();

            //default mode
            Mode = mode;

            //update ui
            splitPanel.Enabled = false;
            buttonCreateDirectory.Enabled = false;
            buttonValidate.Enabled = false;

            //create imageList
            treeViewFtp.ImageList = new ImageList();
            treeViewFtp.ImageList.Images.Add(FolderKey, Resources.Folder);

            //get values from settings
            textBoxHost.Text = Connection.Default.LastFTPHost;
            textBoxLogin.Text = Connection.Default.LastFTPLogin;
            textBoxPassword.Text = Connection.Default.LastFTPPassword;
            textBoxPort.Text = Connection.Default.LastFTPPort;
            checkBoxPassiveMode.Checked = Connection.Default.LastFTPPassiveMode;

            #region System file icon
            _smallImageList.ColorDepth = ColorDepth.Depth32Bit;
            _largeImageList.ColorDepth = ColorDepth.Depth32Bit;

            _smallImageList.ImageSize = new System.Drawing.Size(16, 16);
            _largeImageList.ImageSize = new System.Drawing.Size(32, 32);
            _iconListManager = new IconListManager(_smallImageList, _largeImageList);
            listViewFiles.SmallImageList = _smallImageList;
            listViewFiles.LargeImageList = _largeImageList; 
            #endregion
        } 
        #endregion

        #region Public enumerations
        /// <summary>
        /// Enumération des modes possible de navigation
        /// </summary>
        public enum ModeEnum
        {
            Folder,
            File
        } ; 
        #endregion

        #region Public properties
        /// <summary>
        /// Obtient le chemin complet de la sélection (relatif au site ftp)
        /// ex: /rep1/rep2
        /// </summary>
        public string SelectedRelativeFullPath
        {
            get
            {
                if (_currentNode == null)
                    return "";

                switch (Mode)
                {
                    case ModeEnum.Folder:
                        return GetNodeFullPath(_currentNode, true);
                   
                    case ModeEnum.File:
                        if (listViewFiles.SelectedItems.Count > 0 && listViewFiles.SelectedItems[0] != null)
                            return FtpPathCombine(GetNodeFullPath(_currentNode, true), listViewFiles.SelectedItems[0].Text);
                        return "";

                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
        }

        /// <summary>
        /// Obtient le chemin complet de la sélection (absolu)
        /// ex: ftp://truc.com/rep1/rep2
        /// </summary>
        public string SelectedAbsoluteFullPath
        {
            get
            {
                if (_currentNode == null)
                    return "";

                switch (Mode)
                {
                    case ModeEnum.Folder:
                        return GetNodeFullPath(_currentNode, false);

                    case ModeEnum.File:
                        if (listViewFiles.SelectedItems.Count > 0 && listViewFiles.SelectedItems[0] != null)
                            return FtpPathCombine(GetNodeFullPath(_currentNode, false), listViewFiles.SelectedItems[0].Text);
                        return "";

                    default:
                        throw new ArgumentOutOfRangeException();
                }
            }
        }

        /// <summary>
        /// Accès à l'objet permettant de gérer les fichiers
        /// </summary>
        internal IFileExplorer FileExplorer
        {
            get 
            {
                return _fileExplorer;
            }
        }

        #endregion

        #region Private properties
        /// <summary>
        /// Obtient/modifie le mode d'affichage
        /// </summary>
        private ModeEnum Mode
        {
            get
            {
                return _mode;
            }
            set
            {
                _mode = value;
                UpdateUIWtihMode();
            }
        } 
        #endregion

        #region Private methods        
        
        /// <summary>
        /// Met à jour l'interface selon le mode séléectionné
        /// </summary>
        private void UpdateUIWtihMode()
        {
            switch (Mode)
            {
                case ModeEnum.Folder:
                    splitPanel.Panel2Collapsed = true;
                    buttonCreateDirectory.Visible = true;
                    labelSelection.Text = Resources.RépertoireSélectionné;
                    break;
                case ModeEnum.File:
                    splitPanel.Panel2Collapsed = false;
                    buttonCreateDirectory.Visible = false;
                    labelSelection.Text = Resources.FichierSélectionné;

                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }



        /// <summary>
        /// Gère le chargement de la form
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FtpBrowserLoad(object sender, EventArgs e)
        {
            if (_fileExplorer != null)
                LoadInitialTree(); //reprend les dernières infos de connection
        }

        #region Tree methods
        /// <summary>
        /// Gère la sélection d'un noeud
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TreeViewFtpAfterSelect(object sender, TreeViewEventArgs e)
        {
            //conservation de la selection
            _currentNode = e.Node; 
            
            //en fonction du mode de navigation
            switch (Mode)
            {
                case ModeEnum.Folder:
                    //maj de l'interface
                    textBoxCurrentDir.Text = GetNodeFullPath(e.Node, false);
                    buttonCreateDirectory.Enabled = true;
                    buttonValidate.Enabled = true; 
                    break;

                case ModeEnum.File:
                    textBoxCurrentDir.Text = "";
                    buttonValidate.Enabled = false; 
                    //remplissage réel du noeud
                    listViewFiles.Items.Clear();
                    foreach (string file in _fileExplorer.DirectoryListFiles(GetNodeFullPath(_currentNode, true)))
                        listViewFiles.Items.Add(file, _iconListManager.AddFileIcon(file));
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }


        private void ListViewFilesSelectedIndexChanged(object sender, EventArgs e)
        {
            if (listViewFiles.SelectedItems.Count > 0 && listViewFiles.SelectedItems[0] != null)
            {
                textBoxCurrentDir.Text = FtpPathCombine(GetNodeFullPath(_currentNode, false), listViewFiles.SelectedItems[0].Text);
                buttonValidate.Enabled = true;
            }
            else
            {
                buttonValidate.Enabled = false; 
            }
        }


        /// <summary>
        /// Gére l'expansion d'un noeud
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TreeViewFtpBeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            TreeNode nodeSelected = e.Node;

            if (nodeSelected.Nodes[0].Text == NotYetExpandedFolder)
            {
                // This is a dummy node.
                nodeSelected.Nodes.Clear();

                //remplissage réel du noeud
                foreach (var dir in _fileExplorer.DirectoryListSubDirs(GetNodeFullPath(nodeSelected, true)))
                {
                    TreeNode node = new TreeNode(dir);
                    node.ImageKey = FolderKey;
                    node.Nodes.Add(NotYetExpandedFolder);
                    nodeSelected.Nodes.Add(node);
                }
            }
        }

        /// <summary>
        /// Charge l'arborescence
        /// </summary>
        private void LoadInitialTree()
        {
            try
            {
                treeViewFtp.Nodes.Clear();

                //création du noeud Racine
                TreeNode rootNode = new TreeNode(textBoxHost.Text);
                rootNode.ImageKey = FolderKey;
                //ajout un noeud fils dummy
                rootNode.Nodes.Add(NotYetExpandedFolder);
                treeViewFtp.Nodes.Add(rootNode);
                treeViewFtp.SelectedNode = rootNode;    
                rootNode.Expand();

                //si on arrive jusqu'ici (pas d'exception), alors la connexion est OK

                //activation du panel explorer
                splitPanel.Enabled = true;

                //save connexion info
                Connection.Default.LastFTPHost = textBoxHost.Text;
                Connection.Default.LastFTPLogin = textBoxLogin.Text;
                Connection.Default.LastFTPPassword = textBoxPassword.Text;
                Connection.Default.LastFTPPort = textBoxPort.Text;
                Connection.Default.LastFTPPassiveMode = checkBoxPassiveMode.Checked;
                Connection.Default.Save();

                //désactivation de la partie Connexion
                panelConnectionInfo.Enabled = false;
                buttonConnect.Enabled = false;
                buttonDisconnect.Visible = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show(@"Erreur : " + ex.Message);
                splitPanel.Enabled = false;
            }
        }

        /// <summary>
        /// Obtient le chemin complet d'u noeud
        /// </summary>
        /// <param name="node">le noeud ciblé</param>
        /// <param name="useRealtiveRoot">si true le chemin retourné commence par /   si false commence par le nom d'hôte</param>
        /// <returns>son chemin complet depuis la racine</returns>
        private string GetNodeFullPath(TreeNode node, bool useRealtiveRoot)
        {
            if (node.Parent != null)
            {
                string parentString = GetNodeFullPath(node.Parent, useRealtiveRoot);
                if (parentString.EndsWith(treeViewFtp.PathSeparator))
                    return parentString + node.Text;
                return parentString + treeViewFtp.PathSeparator + node.Text;
            }
            if(useRealtiveRoot)
                return treeViewFtp.PathSeparator;
            return node.Text;
        }
        #endregion

        #region Buttons methods

        /// <summary>
        /// Gère le boutont Connexion
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonConnectClick(object sender, EventArgs e)
        {
            //instancie un nouvel FtpFileExplorer
            _fileExplorer = new FileExplorer.Implementations.FtpFileExplorer(textBoxHost.Text, textBoxLogin.Text, textBoxPassword.Text, textBoxPort.Text, checkBoxPassiveMode.Checked);
            LoadInitialTree();
        }

        /// <summary>
        /// Gère la déconnexion
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonDisconnectClick(object sender, EventArgs e)
        {
            _fileExplorer = null;
            panelConnectionInfo.Enabled = true;
            buttonConnect.Enabled = true;
            buttonDisconnect.Visible = false;
            splitPanel.Enabled = false;
        }

        /// <summary>
        /// Gère la création d'un sous répertoire sur le site FTP
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonCreateDirectoryClick(object sender, EventArgs e)
        {
            //récupération du nom du répertoire
            SingleInput input = new SingleInput("Nom du dossier à créer");
            if (input.ShowDialog() == DialogResult.OK)
            {
                //création du répertoire
                if (_fileExplorer.DirectoryCreate(GetNodeFullPath(_currentNode, true) + treeViewFtp.PathSeparator + input.Value))
                {
                    //on réduit le noeud s'il est expanded
                    if (_currentNode.IsExpanded)
                        _currentNode.Collapse();

                    //insertion d'un noeud "*" pour indiquer qu'il faut le recharger (cf BeforeExpand)
                    _currentNode.Nodes.Insert(0, @"*");

                    //mis à jour du noeud modifié par l'intermédiaire de la fonction TreeViewFtpBeforeExpand
                    TreeViewFtpBeforeExpand(this, new TreeViewCancelEventArgs(_currentNode, false, TreeViewAction.Unknown));
                }
            }
        }

        /// <summary>
        /// Termine le formulaire avec OK comme retour
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonValidateClick(object sender, EventArgs e)
        {
            DialogResult = DialogResult.OK;
            Close();
        }

        /// <summary>
        /// Termine le formulaire avec Cancel comme retour
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonCancelClick(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
            Close();
        }
        #endregion 


        private string FtpPathCombine(string s1, string s2)
        {
            return Path.Combine(s1, s2).Replace("\\", treeViewFtp.PathSeparator);
        }

        #endregion


    }
}
